(function(angular) {
	"use strict";
	angular.module("fs.waf").factory("payDetailService", payDetailService);
	payDetailService.$inject = [ "$injector", "arithService", "formatService", "clsConstants" ];
	function payDetailService($injector, arithService, formatService, clsConstants) {
		var getSetlDetailService = function() {
			return $injector.get("setlDetailService");
		};
		function initPayDetails(settlement) {
			angular.forEach(settlement.payDetails, function(payDetail, index, array) {
				initPayCode(settlement, payDetail);
				payDetail.splitPayDetail_Show = isShowSplitPayDetail(settlement, payDetail);
			});
		}

		function initPayCode(settlement, payDetail) {
			if (!payDetail.payCcy)
				return;
			loadPayCodeForPayDetail(settlement, payDetail);
			var isTransfer = (payDetail.itemSubtype == clsConstants.PayDetailItemSubType.TRANSFER_ITEM);
			setPayDetailAcctInfo(settlement, payDetail, "init", isTransfer);
		}
		
		/***********************************************************************
		 * Only when new add a record, load pay code drop down values and set
		 * default pay acct this item ccy: pay ccy of this item index: the line
		 * number of this item crdr: credit or debit flag of this item:Y or N
		 * isTransfer: true or false indicating whether the
		 * event-source-settlement-detail-item is transfered, only when the
		 * transfer checkbox is checked, the flag is true edited by Steven Hu on
		 * 2006.3.15
		 **********************************************************************/
		function loadPayCodeForPayDetail(settlement, payDetail) {
			// TODO
			var payTypeVal = settlement.payment ? settlement.payment.repayType : "";
			var itemSubtype = payDetail.itemSubtype, list;
			if (payTypeVal == "C" || itemSubtype == clsConstants.PayDetailItemSubType.TRANSFER_ITEM) {
				list = settlement.payCodeList;
			} else {
				list = getSelectedPayCodeObjArr(settlement.payCodeList, payDetail.payCcy);
			}
			payDetail.paycodeOptions = [];
			if (itemSubtype != clsConstants.PayDetailItemSubType.ROLLOVER) {
				if (list != null) {
					angular.forEach(list, function(data, index, array) {
						if (data.usedFor == payDetail.crDrFlag || data.usedFor == "B") {
							var option = {
								"value" : data.paycode,
								"label" : data.paycodeName
							};
							payDetail.paycodeOptions.push(option);
						}
					});
				}
			}else{
				if (list != null) {
					angular.forEach(list, function(data, index, array) {
						if ((data.usedFor == payDetail.crDrFlag || data.usedFor == "B") && data.paycode.substr(7) == clsConstants.PayDetailItemSubType.ROLLOVER) {
							var option = {
								"value" : data.paycode,
								"label" : data.paycodeName
							};
							payDetail.paycodeOptions.push(option);
						}
					});
				}
			}
		}

		function getMaxIndexForPayDetails(payDetails) {
			var resultIndex = 0;
			angular.forEach(payDetails, function(data, index, array) {
				if (data.payItemSeq > resultIndex) {
					resultIndex = data.payItemSeq;
				}
			});
			return resultIndex;
		}

		function getSelectedPayCodeObjArr(arrayList, ccy) {
			var list = [];
			angular.forEach(arrayList, function(data, index, array) {
				if (data.payCcy == ccy || data.payCcy == "*") {
					list.push(data);
				}
			});
			return list;
		}

		/***********************************************************************
		 * set payacct value for each paymentDetail item pdIndex : array index
		 * of paymentDetails pageStatus: whether the settlement init page is
		 * initialed. it can be empty. isTransfer: true or false indicating
		 * whether the event-source-settlement-detail-item is transfered, only
		 * when the transfer checkbox is checked, the flag is true. it can be
		 * empty. edited by Steven Hu on 2006.3.15
		 **********************************************************************/
		// TODO custAcctId encode
		function setPayDetailAcctInfo(settlement, payDetail, pageStatus, isTransfer) {
			var payCcy = payDetail.payCcy;
			var crdr = payDetail.crDrFlag;
			var paycode = payDetail.paycode;
			// TODO
			var payTypeVal = settlement.payment ? settlement.payment.repayType : "";
			var arr;
			if (payTypeVal != null && payTypeVal == "C") {
				arr = settlement.payCodeList;
			} else {
				if (isTransfer)
					arr = settlement.payCodeList;
				else
					arr = getSelectedPayCodeObjArr(settlement.payCodeList, payCcy);
			}
			if (arr == null)
				return false;
			for (var i = 0; i < arr.length; i++) {
				if (arr[i].paycode == paycode && (arr[i].usedFor == crdr || arr[i].usedFor == "B")) {
					payDetail.paycodeName = arr[i].paycodeName;
					payDetail.custAcctFlag = arr[i].custAcctFlag;
					payDetail.paymentCustCode = arr[i].custCode;
					var acctInfoObj = null;
					// this flag judge paycode's account no equals give account.
					var firstCustFlag = false;
					if (pageStatus != "init") {
						payDetail.acctCode = arr[i].acctCode;
						acctInfoObj = getSelectedAcctInfoObj(arr[i].account, payCcy);
					} else {
						acctInfoObj = getSelectedAcctInfoObj(arr[i].account, payCcy);
						if (payDetail.custAcctId && arithService.gt(payDetail.custAcctId, 0)) {
							firstCustFlag = true;
						}
					}
					if (acctInfoObj.custAcctFlag == "Y" || firstCustFlag) {
						payDetail.custAcctType = acctInfoObj.acctNo;
						payDetail.acctType = acctInfoObj.acctType;
						if (settlement.txnSetlInsts != null && settlement.txnSetlInsts.length > 0) {
							var aFlag = false;
							var alloCode = payDetail.allocCode;
							angular.forEach(settlement.txnSetlInsts, function(inst, index) {
								if (!aFlag && !payDetail.paycode && inst.crDr == payDetail.crDrFlag && inst.allocCode == alloCode && inst.setlCcy == payDetail.payCcy
										&& inst.itemType == payDetail.itemType) {
									payDetail.paycode = inst.paycode;
									payDetail.acctNo = inst.acctNo;
									payDetail.custAcctId = inst.custAcctId;
									aFlag = true;
								} else if (!aFlag && payDetail.paycode == inst.paycode && inst.crDr == payDetail.crDrFlag && inst.allocCode == alloCode && inst.setlCcy == payDetail.payCcy
										&& inst.itemType == payDetail.itemType) {
									payDetail.acctNo = inst.acctNo;
									payDetail.custAcctId = inst.custAcctId;
									aFlag = true;
								} else if (!aFlag && payDetail.paycode) {
									payDetail.acctNo = "";
									payDetail.custAcctId = "";
								}
							});
						} else {
							payDetail.acctNo = "";
							payDetail.custAcctId = "";
						}
					} else {
						payDetail.acctNo = acctInfoObj.acctNo;
						payDetail.acctType = acctInfoObj.acctType;
						payDetail.custAcctId = "";
						payDetail.custAcctType = "";
					}
					break;
				}
			}
			initPayDetailConfig(settlement, payDetail);
		}

		function initPayDetailConfig(settlement, payDetail) {
			var acctNoConfig;
			if (payDetail.custAcctFlag == "Y") {
				acctNoConfig = {
					"model" : "acctNo",
					"type" : "lookup-text",
					"gridClass" : "col-sm-12",
					"inputClass" : "input-sm",
					"options" : {
						"title" : "title.lookup.custaccount",
						"id" : "cls.lookupAcctNoList",
						"manualInput" : false,
						"params" : {
							"payDetail" : "<this"
						},
						"boundTo" : {
							"custAcctCode" : "acctNo",
							"custAcctId" : "custAcctId"
						},
						"okEvent" : true,
						"cancelEvent" : false
					}
				};
			} else {
				acctNoConfig = {
					"model" : "acctNo",
					"type" : "text",
					"gridClass" : "col-sm-12",
					"inputClass" : "input-sm",
					"readonly" : true
				};
			}
			payDetail.acctNoConfig = acctNoConfig;
			payDetail.paycodeConfig = {
				"label" : "label.settlement.init.paycode",
				"model" : "paycode",
				"type" : "select",
				"gridClass" : "col-sm-12",
				"inputClass" : "input-sm",
				"options" : {
					"hasEmptyOption": false,
					"data" : payDetail.paycodeOptions,
					"callback" : {
						"changed" : "vm.paycodeChanged"
					}
				}
			};
			if(payDetail.itemType == "D" || payDetail.itemSubtype == clsConstants.PayDetailItemSubType.DISCREPANCY){
				payDetail.allocCodeConfig = {
					"label" : "label.settlement.init.alloc",
					"model" : "allocCode",
					"type" : "select",
					"gridClass" : "col-sm-12",
					"inputClass" : "input-sm",
					"options" : {
						"hasEmptyOption": false,
						"data" : settlement.allocCodeOptions,
						"callback" : {
							"changed" : "vm.payDetailAllocCodeChanged"
						}
					}
				};
			}else{
				payDetail.allocCodeConfig = {
					"label" : "label.settlement.init.alloc",
					"model" : "allocCode",
					"type" : "text",
					"gridClass" : "col-sm-12",
					"inputClass" : "input-sm",
					"readonly": true
				};
			}
			
		}

		function getSelectedAcctInfoObj(account, payCcy) {
			var result = {
				"acctCode" : "",
				"acctCcy" : "",
				"acctNo" : "",
				"acctType" : "",
				"custAcctFlag" : ""
			};
			if (account.acctCcyList) {
				for (var i = 0; i < account.acctCcyList.length; i++) {
					var data = account.acctCcyList[i];
					if (payCcy == data.acctCcy || undefined == data.acctCcy) {
						result = {
							"acctCode" : account.acctCode,
							"acctCcy" : data.acctCcy,
							"acctNo" : account.acctNo,
							"acctType" : account.acctType,
							"custAcctFlag" : account.custAcctFlag
						};
						break;
					}
				}
			}
			if (result.acctCode == "") {
				result = {
					"acctCode" : account.acctCode,
					"acctCcy" : "",
					"acctNo" : account.acctNo,
					"acctType" : account.acctType,
					"custAcctFlag" : account.custAcctFlag
				};
			}
			return result;
		}

		/***********************************************************************
		 * Dynamic change the pay code options in paydetail array.
		 * paydetailIndex: the index of the paydetail array payDetailCcyVal: the
		 * currency of the paydetail array payDetailCrDrVal: the crdr of the
		 * paydetail array
		 **********************************************************************/
		function dynamicChangeThePayCodeList(payDetail, settlement) {
			var itemSubtype = payDetail.itemSubtype;
			var isTransfer = false;
			if (itemSubtype == clsConstants.PayDetailItemSubType.TRANSFER_ITEM)
				isTransfer = true;
			if (itemSubtype != clsConstants.PayDetailItemSubType.ROLLOVER && itemSubtype != clsConstants.PayDetailItemSubType.REMITTANCE) {
				loadPayCodeForPayDetail(settlement, payDetail);
				setPayDetailAcctInfo(settlement, payDetail, null, isTransfer);
			}
		}

		function isUpdateChannelFee(settlement, payDetail) {
			var deductIntFlag = "N";
			var deductFeeFlag = "N";
			if (settlement.deductIntAndFeeFlag) {
				deductIntFlag = settlement.deductIntAndFeeFlag.deductIntFlag;
				deductFeeFlag = settlement.deductIntAndFeeFlag.deductFeeFlag;
			}
			var setlDetails = settlement.setlDetails;
			var isUpdate = false;
			for (var i = 0; i < setlDetails.length; i++) {
				if (setlDetails[i].paydetailSeq == payDetail.payItemSeq) {
					if (!(setlDetails[i].itemSubtype == clsConstants.SetlDetailItemSubType.CHANNEL_FEE || (setlDetails[i].itemType == "I" && deductIntFlag == "Y") || (setlDetails[i].itemType == "F" && deductFeeFlag == "Y"))) {
						isUpdate = true;
					}
				}
			}
			return isUpdate;
		}

		function isShowSplitPayDetail(settlement, payDetail) {
			if (payDetail && settlement) {
				var setlDetailLength = 0;
				angular.forEach(settlement.setlDetails, function(setlDetail, index, array) {
					if (setlDetail.paydetailSeq == payDetail.payItemSeq) {
						setlDetailLength++;
					}
				});
				if (setlDetailLength > 1) {
					return true;
				} else {
					return false;
				}
			} else {
				return false;
			}
		}

		/***********************************************************************
		 * update the payment detail amount according to the operation on
		 * settlement details setldetailIndex: the index of settlement details
		 **********************************************************************/
		function changePaydetailBySetldetail(settlement, setlDetail) {
			if (setlDetail) {
				var payId = setlDetail.paydetailSeq;
				var payAmt = setlDetail.payAmt;
				//If you comment,hold will cause problems.
				if (setlDetail.paydetailSeq_Readonly == true)
					payId = 0;
				// remember the new-linked payment detail's original payCode and account
				var oldCrDr = "";
				var oldPayCode = "";
				var oldAcctNo = "";// payItemSeq
				var isTransfer = false;
				if (payId && (payId - 0) != 0) {
					var oldPaydetail = getPayDetailByPayId(payId, settlement);
					oldCrDr = oldPaydetail.crDrFlag;
					oldPayCode = oldPaydetail.paycode;
					oldAcctNo = oldPaydetail.acctNo;
					if (oldPaydetail.itemSubtype == clsConstants.PayDetailItemSubType.TRANSFER_ITEM)
						isTransfer = true;
					oldPaydetail.splitPayDetail_Show = isShowSplitPayDetail(settlement, oldPaydetail);
				}
				// calculate the paydetail's amount
				setlDetail.payIdA = payId;
				setlDetail.payAmtA = payAmt;

				// delete old
				getSetlDetailService().setlDetailDeleteAmt(settlement, setlDetail, "B");
				// add new
				getSetlDetailService().setlDetailAddAmt(settlement, setlDetail, "A");

				setlDetail.payIdB = setlDetail.payIdA;
				setlDetail.payAmtB = setlDetail.payAmtA;
				if (setlDetail.payIdB) {
					var old_Paydetail = getPayDetailByPayId(setlDetail.payIdB, settlement);
					old_Paydetail.splitPayDetail_Show = isShowSplitPayDetail(settlement, old_Paydetail);
				}
				// refresh the new-linked payment detail's payCode and account
				if (payId && (payId - 0) != 0) {
					var newPaydetail = getPayDetailByPayId(payId, settlement);
					var newCrDr = newPaydetail.crDrFlag;
					if (oldCrDr == newCrDr) {
						newPaydetail.paycode = oldPayCode;
						setPayDetailAcctInfo(settlement, newPaydetail, null, isTransfer);
						newPaydetail.acctNo = oldAcctNo;
						newPaydetail.splitPayDetail_Show = isShowSplitPayDetail(settlement, newPaydetail);
					}
				}
			}
		}

		function getPayDetailByPayId(payId, settlement) {
			var payDetails = settlement.payDetails;
			var payDetail = null;
			angular.forEach(payDetails, function(data, index, array) {
				if (data.payItemSeq == payId) {
					payDetail = data;
				}
			});
			return payDetail;
		}
		;

		/**
		 * add new payment detail item into Summary table, it return the new
		 * item's payItemSeq must check if the new item exist(ccy+allocCode)
		 * before adding youself setlDetail: array index of settlement detail
		 * item which this event source is in, can be empty(only when click
		 * paydetail summary table's add icon) isTransfer: true or false
		 * indicating whether the event-source-settlement-detail-item is
		 * transfered, only when the transfer checkbox is checked, the flag is
		 * true isDiscrepancy: true or false indicating whether the new entry is
		 * a discrepancy, default is false
		 */
		function addPayDetailRow(settlement, setlDetail, isTransfer, isDiscrepancy) {
			var method = getMaxIndexForPayDetails(settlement.payDetails) + 1;
			/*if (settlement.hasDiscrepancy)
				method -= 1;*/
			var payDetail = {};
			payDetail.crDrFlag = setlDetail.crDrFlag;
			payDetail.payCcy = setlDetail.payCcy;
			payDetail.payAmt = 0;
			payDetail.allocCode = setlDetail.allocCode;
			payDetail.payItemSeq = method;
			payDetail.itemType = setlDetail.itemType;
			payDetail.itemSubtype = setlDetail.itemSubtype;
			// TODO
			if (isDiscrepancy) {
				settlement.disEntry = payDetail;
				settlement.hasDiscrepancy = true;
				payDetail.itemSubtype = clsConstants.PayDetailItemSubType.DISCREPANCY;
				payDetail.itemType = "D";
				payDetail.payItemSeq = method;
			}
			settlement.payDetails.push(payDetail);
			if (isTransfer) {
				payDetail.itemSubtype = clsConstants.SetlDetailItemSubType.TRANSFER_ITEM;
			}
			
			// set values to new item's hidden fields: siteCode,setlId
			payDetail.siteCode = settlement.settlementInfo.siteCode;
			payDetail.setlId = settlement.settlementInfo.setlId;
			// 20060808 record the pay method and index of the payment details
			payDetail.splitPayDetail_Show = isShowSplitPayDetail(settlement, payDetail);
			
			getSetlDetailService().refreshPayMethods(settlement);
			// set paycode
			loadPayCodeForPayDetail(settlement, payDetail);
			// set account info
			setPayDetailAcctInfo(settlement, payDetail, null, isTransfer);
			return payDetail;
		}

		function deleteInvalidPayDetail(settlement) {
			for (var i = 0; i < settlement.payDetails.length; i++) {
				var data = settlement.payDetails[i];
				if (data.itemType != "D") {
					// delele item that the amount = 0
					if (!data.payAmt || arithService.eq(formatService.parseMoney(data.payAmt), 0)) {
						settlement.payDetails.splice(i, 1);
						i--;
					}
				}
			}
			getSetlDetailService().refreshPayMethods(settlement);
		}

		return {
			initPayDetails : initPayDetails,
			dynamicChangeThePayCodeList : dynamicChangeThePayCodeList,
			setPayDetailAcctInfo : setPayDetailAcctInfo,
			isShowSplitPayDetail : isShowSplitPayDetail,
			isUpdateChannelFee : isUpdateChannelFee,
			getSelectedPayCodeObjArr : getSelectedPayCodeObjArr,
			getPayDetailByPayId : getPayDetailByPayId,
			changePaydetailBySetldetail : changePaydetailBySetldetail,
			addPayDetailRow : addPayDetailRow,
			deleteInvalidPayDetail : deleteInvalidPayDetail
		};
	}
})(angular);
